package com.github.codemperor.core.lock.redis;

import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;

import java.util.concurrent.TimeUnit;

/**
 * 存储锁（可换成redis）
 */
public class LockContext {
    public static final int maxExpire = 60 * 60 * 24;
    private static ExpiringMap<Object, Object> lockMap = ExpiringMap.builder()
            .variableExpiration() //允许自定义过期
            .maxSize(5000) //设置最大数量
            .expirationPolicy(ExpirationPolicy.CREATED) //基于创建时间过期
            .build();

    /**
     * 设置锁，如果k不存在，则返回null，否则返回存入的v
     *
     * @param k
     * @param expireSec 过期时间（s）
     * @return 设置是否成功
     */
    public static boolean setnx(Object k, int expireSec) {
        // 设置最大的缓存时间，不可以无限大
        if (expireSec > maxExpire) {
            expireSec = maxExpire;
        }
        //不可以为0或者负数
        if (expireSec <= 0) {
            expireSec = maxExpire;
        }
        // 这里直接默认当前日期加上过期时间
        return lockMap.put(k, "FUNNY_LOCK", expireSec, TimeUnit.SECONDS) == null;
    }

    /**
     * 通过锁获取信息
     *
     * @param k
     * @return
     */
    public static boolean isLock(Object k) {
        return lockMap.get(k) != null;
    }

    /**
     * 移除锁
     *
     * @param k
     */
    public static void remove(Object k) {
        lockMap.remove(k);
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("设置锁" + LockContext.setnx("test", 3));
        System.out.println("设置一样的锁" + LockContext.setnx("test", 3));
        System.out.println("查看是否已上锁" + LockContext.isLock("test"));
        Thread.sleep(4000);
        System.out.println("过期后查看是否已上锁" + LockContext.isLock("test"));
        System.out.println("第二次设置锁" + LockContext.setnx("test", 3));

        LockContext.remove("test");
        System.out.println("移除锁后查看是否已上锁" + LockContext.isLock("test"));
        System.out.println("移除锁后查看是否还可以查到锁" + LockContext.lockMap.get("test"));
        Thread.sleep(4000);
    }
}
